package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSearchDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.exceptions.ForbiddenException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author whx
 * @since 2024-12-03
 */
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    @Autowired
    private UserClient userClient;

    @Autowired
    private IInteractionReplyService interactionReplyService;

    @Autowired
    private CourseClient courseClient;

    @Autowired
    private CatalogueClient catalogueClient;

    @Autowired
    private SearchClient searchClient;

    @Autowired
    private CategoryCache categoryCache;

    @Override
    public void addQuestion(QuestionFormDTO dto) {
        Long userId = UserContext.getUser();

        InteractionQuestion interactionQuestion = BeanUtils.toBean(dto, InteractionQuestion.class);

        interactionQuestion.setUserId(userId);

        baseMapper.insert(interactionQuestion);
    }

    @Override
    public PageDTO<QuestionVO> pageQuestion(QuestionPageQuery questionPageQuery) {
        // 获取提问者昵称
        Long userId = UserContext.getUser();

        UserDTO userDTO = userClient.queryUserById(userId);

        Page<InteractionQuestion> page = questionPageQuery.toMpPage();

        this.lambdaQuery()
                .eq(InteractionQuestion::getHidden, false)
                .eq(questionPageQuery.getOnlyMine(), InteractionQuestion::getUserId, userId)
                .eq(ObjectUtil.isNotNull(questionPageQuery.getCourseId()), InteractionQuestion::getCourseId, questionPageQuery.getCourseId())
                .eq(ObjectUtil.isNotNull(questionPageQuery.getSectionId()), InteractionQuestion::getSectionId, questionPageQuery.getSectionId())
                .page(page);

        PageDTO<QuestionVO> pageDTO = PageDTO.of(page, QuestionVO.class);

        for (QuestionVO questionVO : pageDTO.getList()) {
            questionVO.setUserName(userDTO.getName());
            questionVO.setUserIcon(userDTO.getIcon());
        }

        return pageDTO;
    }

    @Override
    public QuestionVO getQuestionById(Long id) {
        Long userId = UserContext.getUser();

        InteractionQuestion interactionQuestion = this.lambdaQuery()
                .eq(InteractionQuestion::getId, id)
                .one();

        if(ObjectUtil.isNull(interactionQuestion)){
            throw new ForbiddenException("该问题不存在");
        }

        UserDTO userDTO = userClient.queryUserById(userId);

        QuestionVO questionVO = BeanUtils.toBean(interactionQuestion, QuestionVO.class);
        questionVO.setUserName(userDTO.getName());
        questionVO.setUserIcon(userDTO.getIcon());

        return questionVO;
    }

    @Override
    public void updateQuestionById(Long id, QuestionFormDTO dto) {
        // 查询问题是否存在
        InteractionQuestion interactionQuestion = getById(id);
        if(ObjectUtil.isNotNull(interactionQuestion)){
            throw new ForbiddenException("该问题不存在");
        }

         interactionQuestion = BeanUtils.toBean(dto, InteractionQuestion.class);

        this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .update(interactionQuestion);
    }

    @Override
    public void deleteById(Long id) {
        // 查询问题是否存在
        InteractionQuestion interactionQuestion = getById(id);
        if(ObjectUtil.isNull(interactionQuestion)){
            throw new ForbiddenException("该问题不存在");
        }

        Long userId = UserContext.getUser();
        if(!interactionQuestion.getUserId().equals(userId)){
            throw new ForbiddenException("不能删除其他人的问题");
        }

        int result = baseMapper.deleteById(id);
        if(result == 0){
            throw new DbException("删除失败");
        }

        // 删除问题下的回答和评论
        LambdaQueryWrapper<InteractionReply> wrapper = Wrappers.<InteractionReply>lambdaQuery()
                .eq(InteractionReply::getQuestionId, id)
                .select();

        interactionReplyService.remove(wrapper);

    }

    @Override
    public void updateQuestionLatestAnswerId(Long id, Long answerId) {
        InteractionQuestion interactionQuestion = getById(id);

        if(ObjectUtil.isNull(interactionQuestion)){
            throw new ForbiddenException("该问题不存在");
        }

        this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getLatestAnswerId, answerId)
                .set(InteractionQuestion::getAnswerTimes, interactionQuestion.getAnswerTimes() + 1)
                .update();
    }

    @Override
    public PageDTO<QuestionAdminVO> pageQuestionsForAdmin(QuestionAdminPageQuery query) {

        List<Long> courseIds = null;

        if(!ObjectUtil.isNull(query.getCourseName())){
             courseIds = searchClient.queryCoursesIdByName(query.getCourseName());

             if(courseIds.size() == 0){
                 return new PageDTO<>();
             }
        }
        
        Long userId = UserContext.getUser();

        UserDTO userDTO = userClient.queryUserById(userId);

        Page<InteractionQuestion> page = query.toMpPage();

        this.lambdaQuery()
                .in(courseIds != null, InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtil.isNotNull(query.getStatus()), InteractionQuestion::getStatus, query.getStatus())
                .between(ObjectUtil.isNotNull(query.getBeginTime()), InteractionQuestion::getCreateTime, query.getBeginTime(), query.getEndTime())
                .page(page);

        List<InteractionQuestion> records = page.getRecords();

        List<QuestionAdminVO> collect = records.stream().map(iq -> {
            CourseSearchDTO courseInfo = courseClient.getSearchInfo(iq.getCourseId());

            List<Long> longs = Arrays.asList(iq.getChapterId(), iq.getSectionId());

            List<CataSimpleInfoDTO> list = catalogueClient.batchQuery(longs);

            QuestionAdminVO questionAdminVO = BeanUtils.toBean(iq, QuestionAdminVO.class);

            List<Long> categoryIdList = ListUtil.toList(courseInfo.getCategoryIdLv1(), courseInfo.getCategoryIdLv2(), courseInfo.getCategoryIdLv3());

            questionAdminVO.setUserName(userDTO.getName());
            questionAdminVO.setCourseName(courseInfo.getName());
            questionAdminVO.setCategoryName(categoryCache.getCategoryNames(categoryIdList));
            questionAdminVO.setChapterName(list.get(0).getName());
            questionAdminVO.setSectionName(list.get(1).getName());

            return questionAdminVO;
        }).collect(Collectors.toList());

        Page<QuestionAdminVO> newPage = query.toMpPage();
        BeanUtil.copyProperties(page, newPage);

        return PageDTO.of(newPage, collect);
    }

    @Override
    public void isHidden(Long id, Boolean hidden) {
        InteractionQuestion interactionQuestion = getById(id);
        if(ObjectUtil.isNull(interactionQuestion)){
            throw new ForbiddenException("该问题不存在");
        }

        if(interactionQuestion.getHidden() == hidden){
            if(hidden){
                throw new ForbiddenException("该问题已被隐藏");
            }else {
                throw new ForbiddenException("该问题已经显示");
            }
        }

        this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, hidden)
                .update();
    }

    @Override
    public QuestionAdminVO getQuestionForAdmin(Long id) {

        InteractionQuestion iq = getById(id);

        if(ObjectUtil.isNull(iq)){
            throw new ForbiddenException("该问题不存在");
        }

        UserDTO userDTO = userClient.queryUserById(iq.getUserId());

        // teacher info
        Long courseId = iq.getCourseId();
        CourseSearchDTO searchDTO = courseClient.getSearchInfo(courseId);
        Long teacherId = searchDTO.getTeacher();
        UserDTO teacherInfo = userClient.queryUserById(teacherId);

        List<Long> longs = Arrays.asList(iq.getChapterId(), iq.getSectionId());

        List<Long> longs1 = Arrays.asList(searchDTO.getCategoryIdLv1(), searchDTO.getCategoryIdLv2(), searchDTO.getCategoryIdLv3());

        List<CataSimpleInfoDTO> list = catalogueClient.batchQuery(longs);

        QuestionAdminVO questionAdminVO = BeanUtils.toBean(iq, QuestionAdminVO.class);
        questionAdminVO.setUserIcon(userDTO.getIcon());
        questionAdminVO.setTeacherName(teacherInfo.getName());
        questionAdminVO.setUserName(userDTO.getName());
        questionAdminVO.setCourseName(searchDTO.getName());
        questionAdminVO.setChapterName(list.get(0).getName());
        questionAdminVO.setSectionName(list.get(1).getName());
        questionAdminVO.setCategoryName(categoryCache.getCategoryNames(longs1));

        // noted status to 1
        if(iq.getStatus().getValue() == QuestionStatus.UN_CHECK.getValue()){
            this.lambdaUpdate()
                    .eq(InteractionQuestion::getId, id)
                    .set(InteractionQuestion::getStatus, QuestionStatus.CHECKED.getValue())
                    .update();
        }

        return questionAdminVO;
    }
}
